package cn.zyjblogs.config.security.granter;

import cn.zyjblogs.starter.common.entity.constant.CommonRedisKeyConstant;
import cn.zyjblogs.starter.common.entity.response.HttpCode;
import cn.zyjblogs.starter.common.exception.AuthRuntimeException;
import cn.zyjblogs.starter.redis.utils.RedisTemplateHandler;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;

import java.util.LinkedHashMap;
import java.util.Map;

public class CaptchaTokenGranter extends AbstractTokenGranter {
    private static final String GRANT_TYPE = "captcha";
    private RedisTemplateHandler<String, String> redisTemplateHandler;
    private AuthenticationManager authenticationManager;

    protected CaptchaTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType) {
        super(tokenServices, clientDetailsService, requestFactory, grantType);
    }

    public CaptchaTokenGranter(RedisTemplateHandler redisTemplateHandler, AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) {
        this(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
        this.redisTemplateHandler = redisTemplateHandler;
        this.authenticationManager = authenticationManager;
    }

    @Override
    protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
        Map<String, String> parameters = new LinkedHashMap<String, String>(tokenRequest.getRequestParameters());
        String captchaId = parameters.get("captchaId");
        String captchaCode = parameters.get("captchaCode");
        String captcha = redisTemplateHandler.get(CommonRedisKeyConstant.CAPTCHA + captchaId);
        if (captcha == null) {
            throw new AuthRuntimeException(HttpCode.BAD_REQUEST, "验证码过期");
        }
        if (!captcha.equals(captchaCode)) {
            throw new AuthRuntimeException(HttpCode.BAD_REQUEST, "验证码错误");
        }
        String username = parameters.get("username");
        String password = parameters.get("password");
        parameters.remove("password");
        Authentication userAuth = new UsernamePasswordAuthenticationToken(username, password);
        ((AbstractAuthenticationToken) userAuth).setDetails(parameters);
        userAuth = authenticationManager.authenticate(userAuth);
        OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
        return new OAuth2Authentication(storedOAuth2Request, userAuth);
    }
}
